package com.fzy.common.file;

import com.fzy.common.util.StringUtil;

import java.io.*;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * 文件处理类
 *
 * @author 冯赵杨
 * @create 2018/8/31
 */
public class FileUtil {

    private FileUtil() {
    }
    
    /**
     * 移动 文件或者文件夹
     *
     * @param oldPath
     * @param newPath
     * @throws IOException
     * @author 冯赵杨
     * @date 2017年6月23日 上午10:38:13
     */
    public static void moveTo(String oldPath, String newPath) throws IOException {
        copyFile(oldPath, newPath);
        deleteFile(oldPath);
    }

    /**
     * 删除 文件或者文件夹
     *
     * @param filePath
     * @author 冯赵杨
     * @date 2017年6月23日 上午10:38:13
     */
    public static void deleteFile(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            return;
        }
        if (file.isDirectory()) {
            File[] list = file.listFiles();
            if (StringUtil.isNotNull(list)) {
                for (File f : list) {
                    deleteFile(f.getAbsolutePath());
                }
            }
        }
        file.delete();
    }

    /**
     * 复制 文件或者文件夹
     *
     * @param oldPath
     * @param newPath
     * @throws IOException
     */
    public static void copyFile(String oldPath, String newPath) throws IOException {
        System.out.println("copy file from [" + oldPath + "] to [" + newPath + "]");

        File oldFile = new File(oldPath);
        if (oldFile.exists()) {
            // 如果是文件夹
            if (oldFile.isDirectory()) {
                File newPathDir = new File(newPath);
                newPathDir.mkdirs();
                File[] lists = oldFile.listFiles();
                if (lists != null && lists.length > 0) {
                    for (File file : lists) {
                        copyFile(file.getAbsolutePath(), newPath.endsWith(File.separator) ? newPath + file.getName()
                                : newPath + File.separator + file.getName());
                    }
                }
            } else {
                //读入原文件
                InputStream inStream = new FileInputStream(oldFile);
                FileOutputStream fs = new FileOutputStream(newPath);
                write2Out(inStream, fs);
                inStream.close();
            }
        }
    }

    /**
     * 重命名文件
     *
     * @param file
     * @param name
     * @return
     */
    public static File renameFile(File file, String name) {
        String fileName = file.getParent() + File.separator + name;
        File dest = new File(fileName);
        file.renameTo(dest);
        return dest;
    }

    /**
     * 压缩多个文件。
     *
     * @param zipFileName 压缩输出文件名
     * @param files       需要压缩的文件
     * @return
     * @throws Exception
     */
    public static File createZip(String zipFileName, File... files) throws Exception {
        File outFile = new File(zipFileName);
        ZipOutputStream out = null;
        BufferedOutputStream bo = null;
        try {
            out = new ZipOutputStream(new FileOutputStream(outFile));
            bo = new BufferedOutputStream(out);

            for (File file : files) {
                zip(out, file, file.getName(), bo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bo != null) {
                    bo.close();
                }
            } finally {
                if (out != null) {
                    out.close(); // 输出流关闭
                }
            }
        }
        return outFile;
    }

    /**
     * @param zipFileName 压缩输出文件名
     * @param inputFile   需要压缩的文件
     * @return
     * @throws Exception
     */
    public static File createZip(String zipFileName, File inputFile) throws Exception {
        File outFile = new File(zipFileName);
        ZipOutputStream out = null;
        BufferedOutputStream bo = null;
        try {
            out = new ZipOutputStream(new FileOutputStream(outFile));
            bo = new BufferedOutputStream(out);
            zip(out, inputFile, inputFile.getName(), bo);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bo != null) {
                bo.close();
            }
            if (out != null) {
                out.close(); // 输出流关闭
            }
        }
        return outFile;
    }

    private static void zip(ZipOutputStream out, File f, String base, BufferedOutputStream bo) throws Exception { // 方法重载
        if (f.isDirectory()) {
            File[] fl = f.listFiles();
            if (fl == null || fl.length == 0) {
                // 创建创建一个空的文件夹
                out.putNextEntry(new ZipEntry(base + "/"));
            } else {
                for (int i = 0; i < fl.length; i++) {
                    // 递归遍历子文件夹
                    zip(out, fl[i], base + "/" + fl[i].getName(), bo);
                }
            }

        } else {
            // 创建zip压缩进入 base 文件
            out.putNextEntry(new ZipEntry(base));
            System.out.println(base);
            BufferedInputStream bi = new BufferedInputStream(new FileInputStream(f));

            try {
                write2Out(bi, out);
            } catch (IOException e) {
                //Ignore
            } finally {
                bi.close();// 输入流关闭
            }
        }
    }

    private static void write2Out(InputStream input, OutputStream out) throws IOException {
        byte[] b = new byte[1024];
        int c;
        while ((c = input.read(b)) != -1) {
            out.write(b, 0, c);
            out.flush();
        }
        out.flush();
    }

    /**
     * 获取月份样式文件路径，格式/yyyyMM/
     *
     * @return
     */
    public static String getMonthCatalog() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        return "/" + sdf.format(new Date()) + "/";
    }

    /**
     * 校正文件路径（去除"//"）
     *
     * @param catalog
     * @return
     */
    public static String regulateCatalog(String catalog) {
        return catalog.replaceAll("//", "/");
    }

    /**
     * 获取文件后缀
     *
     * @param fileName 文件名称
     * @return 文件后缀，如果取不到返回null
     */
    public static String getPostfix(String fileName) {
        if (fileName != null && !"".equals(fileName)) {
            // 文件是否有后缀
            int postion = fileName.lastIndexOf(".");
            if (postion < 1 || postion == (fileName.length() - 1)) {
                return null;
            }
            // 文件后缀
            return fileName.substring(postion + 1);
        } else {
            return null;
        }
    }

    /**
     * 获取一个随机文件名，规则为：年月日时分秒_毫秒数_随机数.后缀
     *
     * @param postfix 文件后缀，如果为null或者""，则为tmp类型
     * @return
     */
    public static String getTmpFileName(String postfix) {
        // 文件后缀
        if ("".equals(postfix)) {
            postfix = ".tmp";
        } else {
            postfix = "." + postfix;
        }
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String msel = date.getTime() + "";
        msel = msel.substring(msel.length() - 3);

        return sdf.format(date) + "_" + msel + "_" + new Random().nextInt(100) + postfix;
    }

    /**
     * 获取一个随机文件名，规则为：定义名_年月日时分秒_毫秒数_随机数.后缀
     *
     * @param defineName 自定义名称
     * @param postfix    文件后缀，如果为null或者""，则为tmp类型
     * @return
     */
    public static String getDefineFileName(String defineName, String postfix) {
        return defineName + "_" + getTmpFileName(postfix);
    }

    /**
     * 创建文件目录
     *
     * @param path 文件目录
     * @return true 成功；false 失败；
     */
    public static boolean mkdirs(String path) {
        path = path.substring(0, path.lastIndexOf("/"));
        try {
            return new File(path).mkdirs();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public String FormetFileSize(long fileS) {//转换文件大小
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString;
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "K";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "M";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "G";
        }
        return fileSizeString;
    }

    public long getlist(File f) {//递归求取目录文件个数
        long size = 0;
        File[] flist = f.listFiles();
        if (flist != null && flist.length > 0) {
            size = flist.length;
            for (File file : flist) {
                if (file.isDirectory()) {
                    size = size + getlist(file);
                    size--;
                }
            }
        }
        return size;

    }

    /**
     * 读取以逗号分隔的文本文件内容，按行读取并把内容转成数组
     *
     * @author 冯赵杨
     * @date 2017年11月8日 下午4:22:10
     */
    public static String[] readTextFile(String filePath) throws IOException {
        FileInputStream fis = new FileInputStream(filePath);
        InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
        BufferedReader br = new BufferedReader(isr);
        String line;
        String[] textAry = null;
        while ((line = br.readLine()) != null) {
            textAry = line.split(",");
        }
        br.close();
        isr.close();
        fis.close();

        return textAry;
    }

    /**
     * 读取以逗号分隔的文本文件内容，按行读取并把内容转成数组
     *
     * @author 冯赵杨
     * @date 2017年11月8日 下午4:22:10
     */
    public static List<String> readTextFile(File file) throws IOException {
        FileInputStream fis = new FileInputStream(file);
        InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
        BufferedReader br = new BufferedReader(isr);
        String line;

        List<String> textList = new ArrayList<>();

        while ((line = br.readLine()) != null) {
            textList.add(line);
        }
        br.close();
        isr.close();
        fis.close();

        return textList;
    }

    /**
     * 遍历文件夹下的所有文件
     *
     * @author 冯赵杨
     * @date 2017年11月8日 下午4:28:35
     */
    public static List<File> getFileList(String folderPath) {
        List<File> filelist = new ArrayList<>();

        File dir = new File(folderPath);
        if (dir.exists()) {
            File[] files = dir.listFiles();
            if (null == files || files.length == 0) {
                return null;
            } else {
                for (File file : files) {
                    if (file.isDirectory()) {
                        getFileList(file.getAbsolutePath());
                    } else {
                        filelist.add(file);
                    }
                }
            }
        }

        return filelist;
    }

}
